package com.tiancikeji.zaoke.app.service.food.impl;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.tiancikeji.zaoke.app.dao.food.FoodTagDao;
import com.tiancikeji.zaoke.app.model.food.FoodTag;
import com.tiancikeji.zaoke.app.service.food.FoodTagService;
import com.tiancikeji.zaoke.app.util.LocalCaches;

@SuppressWarnings("unchecked")
public class FoodTagServiceImpl implements FoodTagService {

	private FoodTagDao foodTagDao;

	private long expireTime;

	public Set<FoodTag> getTagByFoodId(long foodId) {
		Set<Long> foodIds = new HashSet<Long>();
		foodIds.add(foodId);
		Map<Long, Set<FoodTag>> tags = getTagByFoodIds(foodIds);
		if(tags != null && tags.containsKey(foodId))
			return tags.get(foodId);
		return null;
	}

	public Map<Long, Set<FoodTag>> getTagByFoodIds(Set<Long> ids) {
		Map<Long, Set<FoodTag>> result = new HashMap<Long, Set<FoodTag>>();

		List<FoodTag> tags = getAllFoodTags();
		addTags(ids, result, tags);

		Set<Long> remainings = new HashSet<Long>();
		for (Long id : ids)
			if (!result.containsKey(id))
				remainings.add(id);

		if (remainings.size() > 0) {
			tags = foodTagDao.getTagsByFoodIds(remainings);
			addTags(ids, result, tags);
		}

		return result;
	}

	private void addTags(Set<Long> ids, Map<Long, Set<FoodTag>> result,
			List<FoodTag> tags) {
		if (tags != null && tags.size() > 0)
			for (FoodTag tag : tags)
				if (tag != null && ids.contains(tag.getFoodid())){
					Set<FoodTag> tagstmp = result.get(tag.getFoodid());
					if(tagstmp == null){
						tagstmp = new HashSet<FoodTag>();
						result.put(tag.getFoodid(), tagstmp);
					}
					tagstmp.add(tag);
				}
	}

	private List<FoodTag> getAllFoodTags() {
		List<FoodTag> tags = (List<FoodTag>) LocalCaches.get(LocalCaches.ZAOKE_CACHE_TAGS_KEY, System.currentTimeMillis(),expireTime);

		if (tags == null) {
			tags = foodTagDao.getAllTags();

			if (tags != null && tags.size() > 0)
				LocalCaches.set(LocalCaches.ZAOKE_CACHE_TAGS_KEY, tags, System.currentTimeMillis());
		}

		return tags;
	}

	public long getExpireTime() {
		return expireTime;
	}

	public void setExpireTime(long expireTime) {
		this.expireTime = expireTime;
	}

	public FoodTagDao getFoodTagDao() {
		return foodTagDao;
	}

	public void setFoodTagDao(FoodTagDao foodTagDao) {
		this.foodTagDao = foodTagDao;
	}
}
